﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;


namespace ReflectionProgramming
{
    /// <summary>
    /// 强制调用代码，这可以使你随心所欲地调用对象的方法、属性、字段，以及实例化对象。其威力足以毁天灭地！
    /// </summary>
    public class ForcedCall
    {
        /// <summary>
        /// 实例化壹个对象
        /// </summary>
        /// <typeparam name="T">对象泛型</typeparam>
        /// <param name="argc_Value">对象构造字段</param>
        /// <param name="argc_Type">对象构造字段的类型，用来定位是哪个构造方法</param>
        /// <returns>实例化出来的对象</returns>
        public static T ForcedCall_Instantiate<T>(object[] argc_Value, Type[] argc_Type)
        {
            Type type = typeof(T);
            object return_object = type.GetConstructor(
                BindingFlags.Instance
                | System.Reflection.BindingFlags.NonPublic
                | System.Reflection.BindingFlags.Public
                | System.Reflection.BindingFlags.Static
                ,
               Type.DefaultBinder,
               argc_Type,
               null
             ).Invoke(argc_Value);

            return (T)return_object;
        }

        /// <summary>
        /// 调用一个实例的方法，无返回值的
        /// </summary>
        /// <param name="a_Instantiate">实例对象。</param>
        /// <param name="a_name">方法名</param>
        /// <param name="argc_Value">参数字段</param>
        /// <param name="argc_Type">参数字段的类型</param>
        public static void ForcedCall_Method(object a_Instantiate, string a_name, object[] argc_Value, Type[] argc_Type)
        {
            Type type = a_Instantiate.GetType();
            type.GetMethod(
                a_name,
                BindingFlags.Instance
                | System.Reflection.BindingFlags.NonPublic
                | System.Reflection.BindingFlags.Public
                | System.Reflection.BindingFlags.Static
               ,
               Type.DefaultBinder,
               argc_Type,
               null
             ).Invoke(a_Instantiate, argc_Value);
        }

        /// <summary>
        /// 调用一个实例的方法，有返回值的
        /// </summary>
        /// <typeparam name="T">返回对象的泛型</typeparam>
        /// <param name="a_Instantiate">实例对象。</param>
        /// <param name="a_name">方法名</param>
        /// <param name="argc_Value">参数字段</param>
        /// <param name="argc_Type">参数字段的类型</param>
        /// <returns>返回的结果对象</returns>
        public static T ForcedCall_Method<T>(object a_Instantiate, string a_name, object[] argc_Value, Type[] argc_Type)
        {
            Type type = a_Instantiate.GetType();
            object return_object = type.GetMethod(
                a_name,
                BindingFlags.Instance
                | System.Reflection.BindingFlags.NonPublic
                | System.Reflection.BindingFlags.Public
                | System.Reflection.BindingFlags.Static
               ,
               Type.DefaultBinder,
               argc_Type,
               null
             ).Invoke(a_Instantiate, argc_Value);

            return (T)return_object;
        }


        /// <summary>
        /// 调用一个对象的静态方法，无返回值的
        /// </summary>
        /// <param name="a_Instantiate">实例对象。</param>
        /// <param name="a_name">方法名</param>
        /// <param name="argc_Value">参数字段</param>
        /// <param name="argc_Type">参数字段的类型</param>
        public static void ForcedCall_static_Method(Type a_type, string a_name, object[] argc_Value, Type[] argc_Type)
        {
             a_type.GetMethod(
                a_name,
                BindingFlags.Instance
                | System.Reflection.BindingFlags.NonPublic
                | System.Reflection.BindingFlags.Public
                | System.Reflection.BindingFlags.Static
               ,
               Type.DefaultBinder,
               argc_Type,
               null
             ).Invoke(null, argc_Value);
        }

        /// <summary>
        /// 调用一个对象的静态方法，有返回值的
        /// </summary>
        /// <typeparam name="T">返回对象的泛型</typeparam>
        /// <param name="a_type">对象的类型。</param>
        /// <param name="a_name">方法名</param>
        /// <param name="argc_Value">参数字段</param>
        /// <param name="argc_Type">参数字段的类型</param>
        /// <returns>返回的结果对象</returns>
        public static T ForcedCall_static_Method<T>(Type a_type, string a_name, object[] argc_Value, Type[] argc_Type)
        {
            object return_object = a_type.GetMethod(
                a_name,
                BindingFlags.Instance
                | System.Reflection.BindingFlags.NonPublic
                | System.Reflection.BindingFlags.Public
                | System.Reflection.BindingFlags.Static
               ,
               Type.DefaultBinder,
               argc_Type,
               null
             ).Invoke(null, argc_Value);

            return (T)return_object;
        }

        /// <summary>
        /// 获得一个实例的属性(get;set)
        /// </summary>
        /// <typeparam name="T">属性的泛型</typeparam>
        /// <param name="a_Instantiate">对象的实例</param>
        /// <param name="a_name">属性名</param>
        /// <returns>返回属性</returns>
        public static T ForcedCall_Property_Get<T>(object a_Instantiate, string a_name)
        {
            Type type = a_Instantiate.GetType();

            PropertyInfo var_PropertyInfo = type.GetProperty
            (a_name,
                BindingFlags.Instance
                | System.Reflection.BindingFlags.NonPublic
                | System.Reflection.BindingFlags.Public
                | System.Reflection.BindingFlags.Static
            );
            object return_object = var_PropertyInfo.GetValue(a_Instantiate, null);
            if (!var_PropertyInfo.PropertyType.Equals(typeof(T)))
            {
                throw new Exception("PropertyType not Equals T");
            }
            return (T)return_object;
        }

        /// <summary>
        /// 设置一个实例的属性(get;set)
        /// </summary>
        /// <param name="a_Instantiate">对象的实例</param>
        /// <param name="a_name">属性名</param>
        /// <returns>返回属性</returns>
        public static void ForcedCall_Property_Set(object a_Instantiate, string a_name, object a_Value)
        {
            Type type = a_Instantiate.GetType();

            PropertyInfo var_PropertyInfo = type.GetProperty
            (a_name,
                BindingFlags.Instance
                | System.Reflection.BindingFlags.NonPublic
                | System.Reflection.BindingFlags.Public
                | System.Reflection.BindingFlags.Static
            );

            if (!var_PropertyInfo.PropertyType.Equals(a_Value.GetType()))
            {
                throw new Exception("PropertyType not Equals T");
            }
            var_PropertyInfo.SetValue(a_Instantiate, a_Value, null);
        }

        /// <summary>
        /// 获得一个对象的静态属性(get;set)
        /// </summary>
        /// <typeparam name="T">属性的泛型</typeparam>
        /// <param name="a_Instantiate">对象的实例</param>
        /// <param name="a_name">属性名</param>
        /// <returns>返回属性</returns>
        public static T ForcedCall_static_Property_Get<T>(Type a_type, string a_name)
        {
            PropertyInfo var_PropertyInfo = a_type.GetProperty
            (a_name,
                BindingFlags.Instance
                | System.Reflection.BindingFlags.NonPublic
                | System.Reflection.BindingFlags.Public
                | System.Reflection.BindingFlags.Static
            );
            object return_object = var_PropertyInfo.GetValue(null, null);
            if (!var_PropertyInfo.PropertyType.Equals(typeof(T)))
            {
                throw new Exception("PropertyType not Equals T");
            }
            return (T)return_object;
        }

        /// <summary>
        /// 获得一个对象的静态属性(get;set)
        /// </summary>
        /// <param name="a_Instantiate">对象的实例</param>
        /// <param name="a_name">属性名</param>
        /// <returns>返回属性</returns>
        public static void ForcedCall_static_Property_Set(Type a_type, string a_name, object a_Value)
        {
            PropertyInfo var_PropertyInfo = a_type.GetProperty
            (a_name,
                BindingFlags.Instance
                | System.Reflection.BindingFlags.NonPublic
                | System.Reflection.BindingFlags.Public
                | System.Reflection.BindingFlags.Static
            );

            if (!var_PropertyInfo.PropertyType.Equals(a_Value.GetType()))
            {
                throw new Exception("PropertyType not Equals T");
            }
            var_PropertyInfo.SetValue(null, a_Value, null);
        }

        /// <summary>
        /// 获得一个实例的字段（检查字段类型的）
        /// </summary>
        /// <typeparam name="T">字段的泛型</typeparam>
        /// <param name="a_Instantiate">对象的实例</param>
        /// <param name="a_name">字段名</param>
        /// <returns>返回字段</returns>
        public static T ForcedCall_Field_Get<T>(object a_Instantiate, string a_name)
        {
            Type type = a_Instantiate.GetType();

            FieldInfo var_FieldInfo = type.GetField
            (a_name,
                BindingFlags.Instance
                | System.Reflection.BindingFlags.NonPublic
                | System.Reflection.BindingFlags.Public
                | System.Reflection.BindingFlags.Static
            );
            object return_object = var_FieldInfo.GetValue(a_Instantiate);
            if (!var_FieldInfo.FieldType.Equals(typeof(T)))
            {
                throw new Exception("PropertyType not Equals T");
            }
            return (T)return_object;
        }

        /// <summary>
        /// 获得一个实例的字段（不用检查字段类型的）
        /// </summary>
        /// <param name="a_Instantiate">对象</param>
        /// <param name="a_name">字段名</param>
        /// <returns>返回字段</returns>
        public static object ForcedCall_Field_Get(object a_Instantiate, string a_name)
        {
            Type type = a_Instantiate.GetType();

            FieldInfo var_FieldInfo = type.GetField
                (a_name,
                    BindingFlags.Instance
                    | System.Reflection.BindingFlags.NonPublic
                    | System.Reflection.BindingFlags.Public
                    | System.Reflection.BindingFlags.Static
                );
            object return_object = var_FieldInfo.GetValue(a_Instantiate);

            return return_object;
        }

        /// <summary>
        /// 获得一个实例的静态字段（不用检查字段类型的）
        /// </summary>
        /// <param name="a_static_type">对象类型</param>
        /// <param name="a_name">字段名称</param>
        /// <returns>获得的值</returns>
        public static object ForcedCall_static_Field_Get(Type a_static_type, string a_name)
        {

            FieldInfo var_FieldInfo = a_static_type.GetField
                (a_name,
                    BindingFlags.Instance
                    | System.Reflection.BindingFlags.NonPublic
                    | System.Reflection.BindingFlags.Public
                    | System.Reflection.BindingFlags.Static
                );
            object return_object = var_FieldInfo.GetValue(null);
            return return_object;
        }

        /// <summary>
        /// 获得一个实例的静态字段（检查字段类型的）
        /// </summary>
        /// <param name="a_static_type">对象类型</param>
        /// <param name="a_name">字段名称</param>
        /// <returns>获得的值</returns>
        public static T ForcedCall_static_Field_Get<T>(Type a_static_type, string a_name)
        {

            FieldInfo var_FieldInfo = a_static_type.GetField
                (a_name,
                    BindingFlags.Instance
                    | System.Reflection.BindingFlags.NonPublic
                    | System.Reflection.BindingFlags.Public
                    | System.Reflection.BindingFlags.Static
                );
            object return_object = var_FieldInfo.GetValue(null);
            if (!var_FieldInfo.FieldType.Equals(typeof(T)))
            {
                throw new Exception("PropertyType not Equals T");
            }
            return (T)return_object;
        }

        /// <summary>
        /// 设置一个实例的字段
        /// </summary>
        /// <param name="a_Instantiate">对象的实例</param>
        /// <param name="a_name">字段名称</param>
        /// <param name="a_Value">设置的值</param>
        public static void ForcedCall_Field_Set(object a_Instantiate, string a_name, object a_Value)
        {
            Type type = a_Instantiate.GetType();

            FieldInfo var_FieldInfo = type.GetField
            (a_name,
                BindingFlags.Instance
                | System.Reflection.BindingFlags.NonPublic
                | System.Reflection.BindingFlags.Public
                | System.Reflection.BindingFlags.Static
            );

            if (!var_FieldInfo.FieldType.Equals(a_Value.GetType()))
            {
                throw new Exception("PropertyType not Equals T");
            }
            var_FieldInfo.SetValue(a_Instantiate, a_Value);
        }

        /// <summary>
        /// 设置一个对象的静态字段
        /// </summary>
        /// <param name="a_type">对象类型</param>
        /// <param name="a_name">字段名称</param>
        /// <param name="a_Value">设置的值</param>
        public static void ForcedCall_static_Field_Set(Type a_type, string a_name, object a_Value)
        {
            FieldInfo var_FieldInfo = a_type.GetField
            (a_name,
                BindingFlags.Instance
                | System.Reflection.BindingFlags.NonPublic
                | System.Reflection.BindingFlags.Public
                | System.Reflection.BindingFlags.Static
            );
            if (!var_FieldInfo.FieldType.Equals(a_Value.GetType()))
            {
                throw new Exception("PropertyType not Equals T");
            }
            var_FieldInfo.SetValue(null, a_Value);
        }
    }
}
